package com.zhang.controller.communication;

import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSON;
import com.zhang.communication.entity.ChatMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@ServerEndpoint("/ws/{token}")
@Component
public class WebSocketServer {

    private static final String USER_ID = "user_id_";
    private static final ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();

    private String userId;

    // 向指定客户端推送消息
    public static void sendMessage(Session session, String message) {
        try {
            System.out.println("向sid为：" + session.getId() + "，发送：" + message);
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // 向指定用户推送消息
    public static void sendMessage(long userId, String message) {
        Session session = sessionMap.get(USER_ID + userId);
        if (session != null) {
            sendMessage(session, message);
        }
    }

    @OnOpen
    public void onOpen(Session session, @PathParam(value = "token") String token) throws IOException {
        log.info("进入连接");
        String loginUserId = (String) StpUtil.getLoginIdByToken(token);
        if (loginUserId == null) {
            session.close();
            throw new SaTokenException("连接失败，无效Token：" + token);
        }
        userId = loginUserId;
        /*判断是否已经存在，如果已经连接则关闭旧的开启新的连接，防止一个用户多次连接*/
        // 构造用户的唯一会话键
        String sessionKey = USER_ID + loginUserId;
        // 检查是否已经存在该用户的会话
        Session oldSession = sessionMap.get(sessionKey);
        if (oldSession != null && !oldSession.isOpen()) {
            // 如果旧会话已关闭，则移除它（可选）
            sessionMap.remove(sessionKey);
        } else if (oldSession != null && oldSession.isOpen()) {
            // 如果旧会话仍然打开，则关闭它
            oldSession.close();
        }
        // 将新会话添加到映射中
        sessionMap.put(sessionKey, session);
//     TODO   广播上线

    }

    @OnMessage
    public void onMessage(Session session, String message) {
        ChatMessage message1 = JSON.parseObject(message, ChatMessage.class);
        message1.setSendUserId(Long.valueOf(userId));
        long receiver = message1.getReceiveUserId();
        sendMessage(receiver, JSON.toJSONString(message1));
    }

    @OnClose
    public void onClose(Session session) {
        for (String key : sessionMap.keySet()) {
            if (sessionMap.get(key).getId().equals(session.getId())) {
                sessionMap.remove(key);
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("sid为：" + session.getId() + "，发生错误");
        error.printStackTrace();
    }

}
